//CW - NETSH, NET.EXE AND NLTEST HUNT 
//Changes:
//  tuned out firewall rule additions that add new blocks. adjusted wildcards to be greedy
//  adjusted regex after testing to catch more (was missing .exe on some netsh regex)
//  added additional deduplication - events within the same 5 minute bucket (rounded down), with the same devicename and command will be merged
//  added additional expected parent files and tuned out rynagmtr teams activity
let ExpectedActivityParentFile =  pack_array(
    'radics5service.exe' //<--Parent files which need to be tuned out go here, comma separated. e.g, 'one', 'two'
);
DeviceProcessEvents
| where DeviceName startswith "naming.convention" //<-- Enter desired naming convention here, or leave blank to see all devices.
| where InitiatingProcessFileName !in~ (ExpectedActivityParentFile)
//pre-filtering for legit processes
| where not(ProcessCommandLine has_any("redactedfilename")) //<-- Enter any legitimate non-parent software which may trigger this alert here, comma separated (e.g "one", "two")
//normalisation
| extend ProcessCommandLineL=tolower(ProcessCommandLine)
//Net.exe Searching:
| where FileName matches regex @"^net(1)?\.exe$"
    and ProcessCommandLineL matches regex @'(?i)(")?net(1)?\.exe(")? group ("(Domain Admins|AD_ADMINISTRATOR_GROUP)"|(Domain Admins|AD_ADMINISTRATOR_GROUP))(.*)?' // <-- Enter any DOMAIN groups to be monitored here, including AD groups, separated by |, case insensitive
    or ProcessCommandLineL matches regex @'(?i)(")?net(1)?\.exe(")? (user|view|localgroup administrators|localgroup Remote Desktop Users).*' //<-- Enter any LOCAL groups to be monitored here, separated by |, case insensitive
    or ProcessCommandLine matches regex @'(?i)"?net1?(\.exe)?"?\s+stop\s+internet_proxy\.exe(.*)?' //<-- any additional monitored net.exe commands go here - if regex not needed, uncomment line below and add there instead
// or ProcessCommandLine has_any ("") //<-- for additional entries, separate with , (e.g "whoami","netstat")
//Netsh Searching: Note- Currenly only filtering for changes to existing firewall rules, NOT searching for "show" firewall rules as noise is high
    or FileName in ("netsh.exe", "cmd.exe") //regex looks weird because it's looking for obfuscation
        and ProcessCommandLineL matches regex @'(?i).*?"?netsh\.exe?"?\s+a[a-z]{0,10}\s+f[a-z]{0,7}\s+(de[a-z]{0,4}|a[d]{0,2}|se[a-z]{0,1}).*' //translation: netsh advanced firewall delete/add/set
        or ProcessCommandLineL matches regex @'(?i).*?"?netsh\.exe?"?\s+i[a-z]{0,8}\s+p[a-z]{0,8}\s+(a[a-z]{0,2}|s[a-z]{0,2}).*'
        or ProcessCommandLineL matches regex @'(?i).*?"?netsh\.exe?"?\s+w[a-z]{0,6}\s+s[a-z]{0,2}\s+p[a-z]{0,4}\s+.*'
        or ProcessCommandLineL has "netsh trace start"
//nltest hunting- used as standard by many IT environments for troubleshooting, but be cautious for scripting engines (cmd.exe, powershell etc.)
    or FileName =~ "nltest.exe" and AccountName !startswith "naming.convention"
        and ProcessCommandLineL has_any ("/dclist", "/dcname", "/dsgetdc")
        or ProcessCommandLineL has_any ("/sc_query", "/sc_verify", "/sc_reset")
        or ProcessCommandLineL has_all ("/domain_trusts", "/v")
// filtering/tuning
// below regex tunes out any commands that add or remove block rules
| where not(ProcessCommandLineL matches regex @'.*?"?netsh\.exe?"?\s+a[a-z]{0,10}\s+f[a-z]{0,7}\s+(de[a-z]{0,4}|a[d]{0,2}|se[a-z]{0,1})\sr[a-z]{0,3}\sn[a-z]{0,3}="?.*?("\s|\s)(p[a-z]{0,7}=.*?\s)?d[a-z]{0,2}=(in|out)(\s|\sl[a-z]{0,8}=\d{0,5}\s)a[a-z]{0,5}=b[a-z]{0,4}.*')
| extend RoundedTime = bin(Timestamp, 5m)
| summarize any(Timestamp, FileName, FolderPath, AccountName, AccountUpn, InitiatingProcessFileName, InitiatingProcessFolderPath, DeviceId) by RoundedTime, DeviceName, ProcessCommandLine
| project Timestamp=any_Timestamp, DeviceName, FileName=any_FileName, ProcessCommandLine, FolderPath=any_FolderPath, AccountName=any_AccountName, AccountUpn=any_AccountUpn, InitiatingProcessFileName=any_InitiatingProcessFileName, InitiatingProcessFolderPath=any_InitiatingProcessFolderPath, DeviceId=any_DeviceId
| sort by Timestamp desc